package com.lineage.server.utils;

import com.lineage.DatabaseFactory;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class L1QueryUtil {
  private static void setupPrepareStatement(PreparedStatement pstm, Object[] args) throws SQLException {
    int i = 0;
    while (i < args.length) {
      pstm.setObject(i + 1, args[i]);
      i++;
    } 
  }
  
  public static <T> T selectFirst(EntityFactory<T> factory, String sql, Object... args) {
    List<T> result = selectAll(factory, sql, args);
    return result.isEmpty() ? null : result.get(0);
  }
  
  public static <T> List<T> selectAll(EntityFactory<T> factory, String sql, Object... args) {
    ArrayList<T> result = new ArrayList<>();
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement(sql);
      setupPrepareStatement(pstm, args);
      rs = pstm.executeQuery();
      while (rs.next()) {
        T entity = factory.fromResultSet(rs);
        if (entity == null)
          throw new NullPointerException(
              String.valueOf(String.valueOf(String.valueOf(factory.getClass().getSimpleName()))) + " returned null."); 
        result.add(entity);
      } 
    } catch (SQLException e) {
      throw new SecurityException(e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    return result;
  }
  
  public static boolean execute(Connection con, String sql, Object[] args) {
    PreparedStatement pstm = null;
    try {
      pstm = con.prepareStatement(sql);
      setupPrepareStatement(pstm, args);
      boolean bool = pstm.execute();
      return bool;
    } catch (SQLException e) {
      throw new SecurityException(e);
    } finally {
      SQLUtil.close(pstm);
    } 
  }
  
  public static boolean execute(String sql, Object[] args) {
    Connection con = null;
    try {
      con = DatabaseFactory.get().getConnection();
      boolean bool = execute(con, sql, args);
      return bool;
    } catch (SQLException e) {
      throw new SecurityException(e);
    } finally {
      SQLUtil.close(con);
    } 
  }
  
  public static interface EntityFactory<T> {
    T fromResultSet(ResultSet param1ResultSet) throws SQLException;
  }
}
